بناء تطبيق لاختصار الرّوابط باستعمال لغة بايثون وإطار العمل Flask – الجزء الثاني
يمثّل اختصار الروابط واحدة من أكثر الوظائف المطلوبة في الوقت الرّاهن، نظرًا لحاجة المستخدمين والمؤسسات إلى مشاركة روابط قصيرة وسهلة التذكّر، بدلًا من تلك الطويلة والمعقّدة. في الجزء الأوّل من هذا المشروع، تم بناء الأساسيات: إنشاء التطبيق باستخدام Flask، تعريف قاعدة بيانات بسيطة لحفظ الروابط الأصلية والمختصرة، وبناء واجهات الإدخال والاسترجاع. في هذا المقال، نستكمل ما بدأناه من خلال التوسّع في الجوانب التالية: إضافة واجهة مستخدم متقدّمة، تحسين البنية الأمنية، اعتماد نظام إحصائي لتتبع عدد النقرات على الروابط، وتوسيع وظائف قاعدة البيانات باستخدام SQLAlchemy وميزات Flask الحديثة.
1. تعزيز هيكل المشروع وتنظيم الملفات
مع توسع وظائف التطبيق، تصبح بنية المشروع أحد العوامل الحاسمة في سهولة التطوير والصيانة. يُوصى بتقسيم المشروع على الشكل التالي:
arduinourl_shortener/
│
├── app/
│ ├── __init__.py
│ ├── routes.py
│ ├── models.py
│ ├── forms.py
│ ├── utils.py
│ └── templates/
│ ├── base.html
│ ├── index.html
│ └── stats.html
│
├── static/
│ ├── css/
│ │ └── style.css
│ └── js/
│ └── scripts.js
│
├── migrations/
│
├── config.py
├── run.py
└── requirements.txt
هذا النموذج يعتمد مبدأ فصل الاهتمامات، مما يتيح التعامل مع كل جزء من التطبيق على حدة، سواء كان متعلقًا بالمسارات، النماذج، الواجهات، أو الوظائف المساعدة.
2. إنشاء قاعدة البيانات وإدارة العلاقات
في هذا الجزء، سيتم استخدام SQLAlchemy ORM لإدارة الكيانات والتفاعل مع قاعدة البيانات بطريقة كائنية، مما يوفّر أمانًا ومرونة في إدارة البيانات.
models.py
pythonfrom datetime import datetime
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class URL(db.Model):
id = db.Column(db.Integer, primary_key=True)
original_url = db.Column(db.String(2048), nullable=False)
short_url = db.Column(db.String(10), unique=True, nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
visit_count = db.Column(db.Integer, default=0)
هذا النموذج يمثّل الرابط المختصر، ويحتوي على عدد النقرات، التاريخ، والرابط الأصلي، بالإضافة إلى المفتاح الأساسي.
3. إعداد واجهة المستخدم باستخدام Jinja وBootstrap
لكي يكون التطبيق صالحًا للاستخدام العام، من الضروري توفير واجهة استخدام مرنة وسلسة. يمكن استخدام إطار Bootstrap لتصميم واجهات متجاوبة.
templates/index.html
html{% extends "base.html" %}
{% block content %}
<div class="container mt-5">
<h2>اختصر رابطكh2>
<form method="POST">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.original_url.label }}
{{ form.original_url(class="form-control") }}
div>
<button type="submit" class="btn btn-primary mt-2">اختصارbutton>
form>
{% if short_url %}
<div class="alert alert-success mt-4">
رابطك المختصر: <a href="{{ url_for('redirect_to_url', short_url=short_url, _external=True) }}">{{ url_for('redirect_to_url', short_url=short_url, _external=True) }}a>
div>
{% endif %}
div>
{% endblock %}
4. توليد الروابط المختصرة بشكل آمن وفريد
ينبغي أن تكون الروابط المختصرة فريدة وعشوائية لتفادي التضارب، ويمكن استخدام مكتبة secrets لتوليد رموز يصعب تخمينها:
utils.py
pythonimport string
import secrets
from app.models import URL
def generate_short_url(length=6):
characters = string.ascii_letters + string.digits
while True:
short_url = ''.join(secrets.choice(characters) for _ in range(length))
if not URL.query.filter_by(short_url=short_url).first():
break
return short_url
5. إدارة المسارات والردود HTTP
المسارات تتحكم في تدفّق البيانات بين المستخدم والتطبيق، ويجب تقسيمها بطريقة تنظّم المعالجة المنطقية:
routes.py
pythonfrom flask import render_template, request, redirect, url_for, flash
from app import db
from app.forms import URLForm
from app.models import URL
from app.utils import generate_short_url
from flask import Blueprint
bp = Blueprint('main', __name__)
@bp.route('/', methods=['GET', 'POST'])
def index():
form = URLForm()
short_url = None
if form.validate_on_submit():
original_url = form.original_url.data
short_url = generate_short_url()
new_link = URL(original_url=original_url, short_url=short_url)
db.session.add(new_link)
db.session.commit()
return render_template('index.html', form=form, short_url=short_url)
@bp.route('/' )
def redirect_to_url(short_url):
link = URL.query.filter_by(short_url=short_url).first_or_404()
link.visit_count += 1
db.session.commit()
return redirect(link.original_url)
@bp.route('/stats')
def stats():
links = URL.query.order_by(URL.visit_count.desc()).all()
return render_template('stats.html', links=links)
6. تتبع وتحليل الإحصائيات
من أجل مراقبة أداء الروابط، يجب توفير لوحة إحصائية توضح عدد النقرات على كل رابط.
templates/stats.html
html{% extends "base.html" %}
{% block content %}
<div class="container mt-5">
<h2>إحصائيات الروابطh2>
<table class="table table-bordered">
<thead>
<tr>
<th>الرابط الأصليth>
<th>الرابط المختصرth>
<th>عدد النقراتth>
<th>تاريخ الإنشاءth>
tr>
thead>
<tbody>
{% for link in links %}
<tr>
<td>{{ link.original_url }}td>
<td><a href="{{ url_for('main.redirect_to_url', short_url=link.short_url, _external=True) }}">{{ link.short_url }}a>td>
<td>{{ link.visit_count }}td>
<td>{{ link.created_at.strftime('%Y-%m-%d') }}td>
tr>
{% endfor %}
tbody>
table>
div>
{% endblock %}
7. إعداد بيئة التطوير والتشغيل
لضمان تشغيل مستقر للتطبيق على مختلف الأنظمة، يجب اعتماد بيئة افتراضية وربطها بملف متطلبات.
requirements.txt
nginxFlask
Flask-SQLAlchemy
Flask-WTF
WTForms
run.py
pythonfrom app import create_app
app = create_app()
if __name__ == "__main__":
app.run(debug=True)
__init__.py
pythonfrom flask import Flask
from app.models import db
from app.routes import bp
def create_app():
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///urls.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
app.register_blueprint(bp)
with app.app_context():
db.create_all()
return app
8. تحسين الحماية والأداء
لحماية التطبيق من الاستخدام غير المشروع:
-
يجب استخدام HTTPS في النشر.
-
تحديد الطول الأقصى للروابط المُدخلة.
-
منع إدخال روابط ضارة من خلال فحصها.
-
تطبيق قيود على عدد الطلبات (rate limiting) باستخدام أدوات مثل Flask-Limiter.
-
استخدام headers مثل Content-Security-Policy وX-Frame-Options.
9. نشر التطبيق على الإنترنت
يمكن نشر التطبيق عبر منصات مثل Render, Heroku, أو خوادم مثل Gunicorn مع NGINX. الخطوات الأساسية تشمل:
-
إعداد ملف
Procfile(لـ Heroku). -
استخدام
gunicornكمخدم تطبيق. -
تحميل المتطلبات عبر
pip install -r requirements.txt. -
إجراء ترحيلات قاعدة البيانات.
جدول توضيحي للوظائف والمكوّنات
| الوظيفة | الملف المسؤول | الوصف العام |
|---|---|---|
| تعريف قاعدة البيانات | models.py |
يحتوي على نموذج URL للروابط والزيارات |
| توليد روابط مختصرة | utils.py |
يُنتج رموزًا فريدة باستعمال خوارزمية تعتمد على secrets |
| صفحة إدخال الرابط | index.html |
واجهة مستخدم تطلب الرابط الأصلي وتعرض المختصر |
| تتبّع النقرات | redirect_to_url() |
يُسجّل عدد مرات النقر على الرابط المختصر |
| عرض الإحصائيات | stats.html |
جدول يعرض الروابط وعدد زياراتها |
| المسارات | routes.py |
تنظيم الوظائف والربط بين الواجهات الخلفية والأمامية |
| تهيئة التطبيق | __init__.py |
إعداد Flask وربط قاعدة البيانات والمخططات |
| تشغيل التطبيق | run.py |
نقطة البدء لتشغيل التطبيق |
| المتطلبات | requirements.txt |
تحديد المكتبات اللازمة للتشغيل |
المراجع
-
Flask Documentation – https://flask.palletsprojects.com
-
SQLAlchemy ORM Tutorial – https://docs.sqlalchemy.org/en/20/orm/tutorial.html

